package com.sinai.mshab.client.widgets;

import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.sinai.mshab.client.Mshab;
import com.sinai.mshab.client.formatting.ClonableWidget;
import com.sinai.mshab.client.formatting.CloneManager;

/**
 * This table will clone the widgets in it's rows.
 * 
 * @author serge
 * 
 */
public class ExpandableTable extends FlexTable {

	private int colCount = 0;
	private Label add_row_label;
	private boolean remove_links;
	private CloseListener close_listener;

	/**
	 * Creates a new expandable table.
	 * 
	 * @param more_message
	 *            the message to use under the rows for cloning.
	 */
	public ExpandableTable(String more_message) {

		setStyleName("mshab-ExpandableTable");

		// create a close listener
		close_listener = new CloseListener();

		// by default we do not use remove links.
		remove_links = false;

		// adding a row for the row duplicator label.
		HorizontalPanel another_panel = new HorizontalPanel();
		another_panel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
		Image another = Mshab.getImageBundle().getPlus().createImage();
		another.setStyleName("mshab-cursorImage");
		another.addClickListener(new DuplicateRowListener());
		another_panel.add(another);
		add_row_label = new Label(more_message);
		add_row_label.addClickListener(new DuplicateRowListener());
		add_row_label.setStyleName("mshab-addRowLabel");
		another_panel.add(add_row_label);

		setWidget(2, 0, another_panel);
	}

	/**
	 * Adds a widget to the first row of the table.
	 * 
	 * @param widget
	 *            the widget to be added.
	 */
	public void add(Widget widget) {
		add(widget, "");
	}

	/**
	 * Adds a widget to the first row of the table with a title.
	 * 
	 * @param widget
	 *            the widget to be added.
	 * @param title
	 *            the title of the column of this widget.
	 */
	public void add(Widget widget, String title) {
		// if we care about remove links, handle them.
		if (remove_links) {
			insertCell(1, colCount - 1);

			// insert the new widget into the first row.
			setWidget(1, colCount - 1, widget);

			// add header
			Label header = new Label(title);
			header.setStyleName("mshab-ColumnHeader");
			setWidget(0, colCount - 1, header);

			colCount++;
		}
		// if we don't care about remove links, ignore them
		else {
			// insert the new widget into the first row.
			setWidget(1, colCount, widget);

			// add header
			Label header = new Label(title);
			header.setStyleName("mshab-ColumnHeader");
			setWidget(0, colCount, header);

			colCount++;
		}

		// increase the colspan on the duplicator row so it does not interfere
		// with the rest of the table formatting
		getFlexCellFormatter().setColSpan(getRowCount() - 1, 0, colCount);
	}

	/**
	 * Adds an additional row and duplicates all widgets from the previous row.
	 */
	public void addRow() {
		int rows = getRowCount();
		int cols = getCellCount(1);
		int new_row = rows - 1;

		// nothing to do.
		if (cols == 0) {
			return;
		}

		// inserting the new row.
		insertRow(new_row);

		// duplicate all the cols.
		for (int i = 0; i < cols; i++) {

			if (i < cols - 1) {
				// the widget that we need to clone
				Widget current = getWidget(1, i);

				// check if it's clonable, if so clone it.
				if (current instanceof ClonableWidget) {
					setWidget(new_row, i, ((ClonableWidget) current)
							.cloneWidget());
				}
				// else let clone manager clone it for us.
				else {
					Widget new_widget = CloneManager.clone(current);
					setWidget(new_row, i, new_widget);
				}
			}
			else {
				setWidget(new_row, i, Mshab.getImageBundle().getClose().createImage());
			}
		}

		// fix up any remove links if we use them
		if (remove_links) {
			fixRemoveLinks();
		}
	}

	/**
	 * Specifies that this panel will have the ability to remove it's elements.
	 */
	public void includeRemoveLinks() {
		remove_links = true;
		Image remove_img = Mshab.getImageBundle().getClose().createImage();
		remove_img.setVisible(false);
		setWidget(1, 0, remove_img);
		colCount++;
	}

	/**
	 * This method will make sure you can't close the last row.
	 */
	private void fixRemoveLinks() {
		int rows = getRowCount();
		int close_index = getCellCount(1) - 1;

		// if we have more than 1 row kicking around
		if (rows > 3) {

			// turn on all close links and insure they are listening.
			for (int i = 1; i < rows - 1; i++) {
				Widget close = getWidget(i, close_index);
				if (close instanceof Image) {
					Image cur = (Image) close;
					cur.setStyleName("mshab-cursorImage");
					cur.setVisible(true);
					cur.addClickListener(close_listener);
				}
			}
		}
		// if there is only one row, make sure it can't be removed.
		else {
			Widget close = getWidget(1, close_index);
			if (close instanceof Image) {
				close.setVisible(false);
			}
		}

	}

	/**
	 * Clears the table of all cells
	 */
	public void clear() {
		colCount = 0;
		super.clear();
	}

	/**
	 * Removed a row of a given close image.
	 * 
	 * @param of
	 *            the close image of the row to be removed.
	 */
	private void removeRow(Widget of) {
		int rows = getRowCount();
		int close_index = getCellCount(1) - 1;

		// go through all the close buttons, see which one complained and nuke
		// it's row.
		for (int i = 1; i < rows - 1; i++) {
			Widget close = getWidget(i, close_index);
			if (close == of) {
				removeRow(i);
				fixRemoveLinks();
				return;
			}
		}
	}

	private class DuplicateRowListener implements ClickListener {
		public void onClick(Widget sender) {
			addRow();
		}
	}

	private class CloseListener implements ClickListener {
		public void onClick(Widget sender) {
			removeRow(sender);
		}
	}
}
